#include <stdlib.h>
#include <string.h>
#include "map.h"

static const uint32_t map_init_cap = 32;

struct map_entry_st
{
    void *key;
    void *val;
    // 发生hash冲突时,启用开链法
    struct map_entry_st *next;
};

/// @brief 内部函数 初始化 map_entry_t
/// @param key
/// @param value
/// @return
static inline map_entry_t *__map_entry_init(void *key, void *value)
{
    map_entry_t *ptr = NULL;

    ptr = calloc(1, sizeof(map_entry_t));
    if (ptr == NULL)
        goto fail0;
    ptr->key = key;
    ptr->val = value;
fail0:
    return ptr;
}

/// @brief 内部函数 释放 map_entry_t
/// @param entry
static inline void __map_entry_deinit(map_entry_t *entry)
{
    if (entry != NULL)
        free(entry);
}

/// @brief 外部函数 初始化map
/// @param map map_t 变量地址
/// @param hash_fn 指定hash函数
/// @param equal_fn 指定equal函数
/// @param deinit_before_fn deinit map桶内元素释放函数
void map_init(map_t *map, map_hash_impl hash_fn, map_equal_impl equal_fn, map_deinit_before_impl deinit_before_fn)
{
    if (hash_fn == NULL || equal_fn == NULL)
        return;
    map->hash_fn = hash_fn;
    map->equal_fn = equal_fn;
    map->deinit_before_fn = deinit_before_fn;
    map->used = 0;
    map->cap = map_init_cap;
    // 数据容器初始化
    map->entrys = (map_entry_t **)calloc(map->cap, sizeof(map_entry_t *));
    if ((map->entrys) != NULL)
        memset(map->entrys, 0, (map->cap * sizeof(map_entry_t *)));
}

/// @brief 外部函数 初始化map 允许定义hashtable容量
/// @param map map_t 变量地址
/// @param cap 容器容量 容量
/// @param hash_fn 指定hash函数
/// @param equal_fn 指定equal函数
/// @param deinit_before_fn deinit map桶内元素释放函数
void map_init1(map_t *map, uint32_t cap, map_hash_impl hash_fn, map_equal_impl equal_fn, map_deinit_before_impl deinit_before_fn)
{
    if (hash_fn == NULL || equal_fn == NULL)
        return;
    map->hash_fn = hash_fn;
    map->equal_fn = equal_fn;
    map->deinit_before_fn = deinit_before_fn;
    map->used = 0;
    map->cap = cap;
    // 数据容器初始化
    map->entrys = (map_entry_t **)calloc(map->cap, sizeof(map_entry_t *));
    if ((map->entrys) != NULL)
        memset(map->entrys, 0, (map->cap * sizeof(map_entry_t *)));
}

/// @brief 外部函数 释放map
/// @param map map_t 变量地址
void map_deinit(map_t *map)
{
    if (map == NULL)
        return;
    for (int i = 0; i < map->cap; i++)
    {
        map_entry_t *e = (map->entrys[i]);
        map_entry_t *next = (map->entrys[i]);
        while (e)
        {
            next = e->next;
            if (map->deinit_before_fn != NULL)
                map->deinit_before_fn(e->key, e->val);
            __map_entry_deinit(e);
            map->used--;
            e = next;
        }
    }
    free(map->entrys);
}

/// @brief 外部函数 往map中放入键值对
/// @param map map_t 变量地址
/// @param key 地址
/// @param keylen key变量真实长度
/// @param value 地址
/// @return 成功:0 失败:-1=> 参数错误 1:已经存在该key
int8_t map_put(map_t *map, void *key, uint32_t keylen, void *value)
{
    if (map == NULL || map->hash_fn == NULL || map->equal_fn == NULL)
        return -1;
    uint32_t idx = map->hash_fn(key, keylen) % map->cap;
    map_entry_t *e = (map->entrys[idx]);
    while (e != NULL)
    {
        int equal_ret = map->equal_fn(e->key, key);
        if (equal_ret == 1)
            return 1;
        e = e->next;
    }
    map_entry_t *new_e = __map_entry_init(key, value);
    new_e->next = (map->entrys[idx]);
    map->entrys[idx] = new_e;
    map->used++;
    return 0;
}

/// @brief 外部函数 获取map中键对应的值
/// @param map map_t 变量地址
/// @param key
/// @param keylen
/// @return 存在返回void *变量;失败返回NULL
void *map_get(map_t *map, void *key, uint32_t keylen)
{
    if (map == NULL || map->hash_fn == NULL || map->equal_fn == NULL)
        return NULL;
    uint32_t idx = map->hash_fn(key, keylen) % map->cap;
    map_entry_t *e = (map->entrys[idx]);
    while (e != NULL)
    {
        int equal_ret = map->equal_fn(e->key, key);
        if (equal_ret == 1)
            return e->val;
        e = e->next;
    }
    return NULL;
}

/// @brief 外部函数 删除map中指定键值对
/// @param map map_t 变量地址
/// @param key
/// @param keylen 成功:0 失败:-1=>参数异常 1:没找到指定key
/// @return
int8_t map_del(map_t *map, void *key, uint32_t keylen)
{
    if (map == NULL || map->hash_fn == NULL || map->equal_fn == NULL)
        return -1;
    uint32_t idx = map->hash_fn(key, keylen) % map->cap;
    map_entry_t **prev = &(map->entrys[idx]);
    map_entry_t *e = (map->entrys[idx]);
    while (e != NULL)
    {
        if (map->equal_fn(e->key, key))
        {
            *prev = e->next;
            __map_entry_deinit(e);
            map->used--;
            return 0;
        }
        *prev = e;
        e = e->next;
    }
    return 1;
}

/// @brief 外部函数 遍历map
/// @param map map_t 变量地址
/// @param foreach_fn foreach函数 指定返回值为-1时跳出循环
/// @param userdata 用户自定义数据地址
/// @return 返回foreach函数累加数据
int64_t map_foreach(map_t *map, map_foreach_impl foreach_fn, void *userdata)
{
    if (map == NULL || foreach_fn == NULL)
        return -1;
    int64_t sum = 0;
    for (int i = 0; i < map->cap; i++)
    {
        map_entry_t *e = (map->entrys[i]);
        map_entry_t *next = (map->entrys[i]);
        while (e)
        {
            next = e->next;
            int foreach_ret = foreach_fn((const void *)e->key, e->val, userdata);
            if (foreach_ret == -1)
                goto fail0;
            sum += foreach_ret;
            e = next;
        }
    }
fail0:
    return sum;
}

/// @brief 外部函数 map使用情况
/// @param map map_t 变量地址
void map_used(map_t *map)
{
    if (map == NULL)
        return;
    printf("======map %p======\n", map);
    printf("cap:%d used:%d\n", map->cap, map->used);
    for (size_t i = 0; i < map->cap; i++)
    {
        size_t count = 0;
        map_entry_t *e = (map->entrys[i]);
        printf("\t======map[%ld]======\n", i);
        while (e)
        {
            printf("\t\tkey:%p,value:%p\n", e->key, e->val);
            count++;
            e = e->next;
        }
        printf("\t======map[%ld] len:%ld ======\n", i, count);
    }
    printf("cap:%d used:%d\n", map->cap, map->used);
    printf("============\n");
}